home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / idlelib / run.py < prev    next >
Text File  |  2008-10-05  |  11KB  |  331 lines

  1. import sys
  2. import os
  3. import linecache
  4. import time
  5. import socket
  6. import traceback
  7. import thread
  8. import threading
  9. import Queue
  10.  
  11. import CallTips
  12. import AutoComplete
  13.  
  14. import RemoteDebugger
  15. import RemoteObjectBrowser
  16. import StackViewer
  17. import rpc
  18.  
  19. import __main__
  20.  
  21. LOCALHOST = '127.0.0.1'
  22.  
  23. try:
  24.     import warnings
  25. except ImportError:
  26.     pass
  27. else:
  28.     def idle_formatwarning_subproc(message, category, filename, lineno):
  29.         """Format warnings the IDLE way"""
  30.         s = "\nWarning (from warnings module):\n"
  31.         s += '  File \"%s\", line %s\n' % (filename, lineno)
  32.         line = linecache.getline(filename, lineno).strip()
  33.         if line:
  34.             s += "    %s\n" % line
  35.         s += "%s: %s\n" % (category.__name__, message)
  36.         return s
  37.     warnings.formatwarning = idle_formatwarning_subproc
  38.  
  39. # Thread shared globals: Establish a queue between a subthread (which handles
  40. # the socket) and the main thread (which runs user code), plus global
  41. # completion and exit flags:
  42.  
  43. exit_now = False
  44. quitting = False
  45.  
  46. def main(del_exitfunc=False):
  47.     """Start the Python execution server in a subprocess
  48.  
  49.     In the Python subprocess, RPCServer is instantiated with handlerclass
  50.     MyHandler, which inherits register/unregister methods from RPCHandler via
  51.     the mix-in class SocketIO.
  52.  
  53.     When the RPCServer 'server' is instantiated, the TCPServer initialization
  54.     creates an instance of run.MyHandler and calls its handle() method.
  55.     handle() instantiates a run.Executive object, passing it a reference to the
  56.     MyHandler object.  That reference is saved as attribute rpchandler of the
  57.     Executive instance.  The Executive methods have access to the reference and
  58.     can pass it on to entities that they command
  59.     (e.g. RemoteDebugger.Debugger.start_debugger()).  The latter, in turn, can
  60.     call MyHandler(SocketIO) register/unregister methods via the reference to
  61.     register and unregister themselves.
  62.  
  63.     """
  64.     global exit_now
  65.     global quitting
  66.     global no_exitfunc
  67.     no_exitfunc = del_exitfunc
  68.     port = 8833
  69.     #time.sleep(15) # test subprocess not responding
  70.     if sys.argv[1:]:
  71.         port = int(sys.argv[1])
  72.     sys.argv[:] = [""]
  73.     sockthread = threading.Thread(target=manage_socket,
  74.                                   name='SockThread',
  75.                                   args=((LOCALHOST, port),))
  76.     sockthread.setDaemon(True)
  77.     sockthread.start()
  78.     while 1:
  79.         try:
  80.             if exit_now:
  81.                 try:
  82.                     exit()
  83.                 except KeyboardInterrupt:
  84.                     # exiting but got an extra KBI? Try again!
  85.                     continue
  86.             try:
  87.                 seq, request = rpc.request_queue.get(block=True, timeout=0.05)
  88.             except Queue.Empty:
  89.                 continue
  90.             method, args, kwargs = request
  91.             ret = method(*args, **kwargs)
  92.             rpc.response_queue.put((seq, ret))
  93.         except KeyboardInterrupt:
  94.             if quitting:
  95.                 exit_now = True
  96.             continue
  97.         except SystemExit:
  98.             raise
  99.         except:
  100.             type, value, tb = sys.exc_info()
  101.             try:
  102.                 print_exception()
  103.                 rpc.response_queue.put((seq, None))
  104.             except:
  105.                 # Link didn't work, print same exception to __stderr__
  106.                 traceback.print_exception(type, value, tb, file=sys.__stderr__)
  107.                 exit()
  108.             else:
  109.                 continue
  110.  
  111. def manage_socket(address):
  112.     for i in range(3):
  113.         time.sleep(i)
  114.         try:
  115.             server = MyRPCServer(address, MyHandler)
  116.             break
  117.         except socket.error, err:
  118.             print>>sys.__stderr__,"IDLE Subprocess: socket error: "\
  119.                                         + err[1] + ", retrying...."
  120.     else:
  121.         print>>sys.__stderr__, "IDLE Subprocess: Connection to "\
  122.                                "IDLE GUI failed, exiting."
  123.         show_socket_error(err, address)
  124.         global exit_now
  125.         exit_now = True
  126.         return
  127.     server.handle_request() # A single request only
  128.  
  129. def show_socket_error(err, address):
  130.     import Tkinter
  131.     import tkMessageBox
  132.     root = Tkinter.Tk()
  133.     root.withdraw()
  134.     if err[0] == 61: # connection refused
  135.         msg = "IDLE's subprocess can't connect to %s:%d.  This may be due "\
  136.               "to your personal firewall configuration.  It is safe to "\
  137.               "allow this internal connection because no data is visible on "\
  138.               "external ports." % address
  139.         tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
  140.     else:
  141.         tkMessageBox.showerror("IDLE Subprocess Error", "Socket Error: %s" % err[1])
  142.     root.destroy()
  143.  
  144. def print_exception():
  145.     import linecache
  146.     linecache.checkcache()
  147.     flush_stdout()
  148.     efile = sys.stderr
  149.     typ, val, tb = excinfo = sys.exc_info()
  150.     sys.last_type, sys.last_value, sys.last_traceback = excinfo
  151.     tbe = traceback.extract_tb(tb)
  152.     print>>efile, '\nTraceback (most recent call last):'
  153.     exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
  154.                "RemoteDebugger.py", "bdb.py")
  155.     cleanup_traceback(tbe, exclude)
  156.     traceback.print_list(tbe, file=efile)
  157.     lines = traceback.format_exception_only(typ, val)
  158.     for line in lines:
  159.         print>>efile, line,
  160.  
  161. def cleanup_traceback(tb, exclude):
  162.     "Remove excluded traces from beginning/end of tb; get cached lines"
  163.     orig_tb = tb[:]
  164.     while tb:
  165.         for rpcfile in exclude:
  166.             if tb[0][0].count(rpcfile):
  167.                 break    # found an exclude, break for: and delete tb[0]
  168.         else:
  169.             break        # no excludes, have left RPC code, break while:
  170.         del tb[0]
  171.     while tb:
  172.         for rpcfile in exclude:
  173.             if tb[-1][0].count(rpcfile):
  174.                 break
  175.         else:
  176.             break
  177.         del tb[-1]
  178.     if len(tb) == 0:
  179.         # exception was in IDLE internals, don't prune!
  180.         tb[:] = orig_tb[:]
  181.         print>>sys.stderr, "** IDLE Internal Exception: "
  182.     rpchandler = rpc.objecttable['exec'].rpchandler
  183.     for i in range(len(tb)):
  184.         fn, ln, nm, line = tb[i]
  185.         if nm == '?':
  186.             nm = "-toplevel-"
  187.         if not line and fn.startswith("<pyshell#"):
  188.             line = rpchandler.remotecall('linecache', 'getline',
  189.                                               (fn, ln), {})
  190.         tb[i] = fn, ln, nm, line
  191.  
  192. def flush_stdout():
  193.     try:
  194.         if sys.stdout.softspace:
  195.             sys.stdout.softspace = 0
  196.             sys.stdout.write("\n")
  197.     except (AttributeError, EOFError):
  198.         pass
  199.  
  200. def exit():
  201.     """Exit subprocess, possibly after first deleting sys.exitfunc
  202.  
  203.     If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
  204.     sys.exitfunc will be removed before exiting.  (VPython support)
  205.  
  206.     """
  207.     if no_exitfunc:
  208.         try:
  209.             del sys.exitfunc
  210.         except AttributeError:
  211.             pass
  212.     sys.exit(0)
  213.  
  214. class MyRPCServer(rpc.RPCServer):
  215.  
  216.     def handle_error(self, request, client_address):
  217.         """Override RPCServer method for IDLE
  218.  
  219.         Interrupt the MainThread and exit server if link is dropped.
  220.  
  221.         """
  222.         global quitting
  223.         try:
  224.             raise
  225.         except SystemExit:
  226.             raise
  227.         except EOFError:
  228.             global exit_now
  229.             exit_now = True
  230.             thread.interrupt_main()
  231.         except:
  232.             erf = sys.__stderr__
  233.             print>>erf, '\n' + '-'*40
  234.             print>>erf, 'Unhandled server exception!'
  235.             print>>erf, 'Thread: %s' % threading.currentThread().getName()
  236.             print>>erf, 'Client Address: ', client_address
  237.             print>>erf, 'Request: ', repr(request)
  238.             traceback.print_exc(file=erf)
  239.             print>>erf, '\n*** Unrecoverable, server exiting!'
  240.             print>>erf, '-'*40
  241.             quitting = True
  242.             thread.interrupt_main()
  243.  
  244.  
  245. class MyHandler(rpc.RPCHandler):
  246.  
  247.     def handle(self):
  248.         """Override base method"""
  249.         executive = Executive(self)
  250.         self.register("exec", executive)
  251.         sys.stdin = self.console = self.get_remote_proxy("stdin")
  252.         sys.stdout = self.get_remote_proxy("stdout")
  253.         sys.stderr = self.get_remote_proxy("stderr")
  254.         import IOBinding
  255.         sys.stdin.encoding = sys.stdout.encoding = \
  256.                              sys.stderr.encoding = IOBinding.encoding
  257.         self.interp = self.get_remote_proxy("interp")
  258.         rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
  259.  
  260.     def exithook(self):
  261.         "override SocketIO method - wait for MainThread to shut us down"
  262.         time.sleep(10)
  263.  
  264.     def EOFhook(self):
  265.         "Override SocketIO method - terminate wait on callback and exit thread"
  266.         global quitting
  267.         quitting = True
  268.         thread.interrupt_main()
  269.  
  270.     def decode_interrupthook(self):
  271.         "interrupt awakened thread"
  272.         global quitting
  273.         quitting = True
  274.         thread.interrupt_main()
  275.  
  276.  
  277. class Executive(object):
  278.  
  279.     def __init__(self, rpchandler):
  280.         self.rpchandler = rpchandler
  281.         self.locals = __main__.__dict__
  282.         self.calltip = CallTips.CallTips()
  283.         self.autocomplete = AutoComplete.AutoComplete()
  284.  
  285.     def runcode(self, code):
  286.         try:
  287.             self.usr_exc_info = None
  288.             exec code in self.locals
  289.         except:
  290.             self.usr_exc_info = sys.exc_info()
  291.             if quitting:
  292.                 exit()
  293.             # even print a user code SystemExit exception, continue
  294.             print_exception()
  295.             jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
  296.             if jit:
  297.                 self.rpchandler.interp.open_remote_stack_viewer()
  298.         else:
  299.             flush_stdout()
  300.  
  301.     def interrupt_the_server(self):
  302.         thread.interrupt_main()
  303.  
  304.     def start_the_debugger(self, gui_adap_oid):
  305.         return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
  306.  
  307.     def stop_the_debugger(self, idb_adap_oid):
  308.         "Unregister the Idb Adapter.  Link objects and Idb then subject to GC"
  309.         self.rpchandler.unregister(idb_adap_oid)
  310.  
  311.     def get_the_calltip(self, name):
  312.         return self.calltip.fetch_tip(name)
  313.  
  314.     def get_the_completion_list(self, what, mode):
  315.         return self.autocomplete.fetch_completions(what, mode)
  316.  
  317.     def stackviewer(self, flist_oid=None):
  318.         if self.usr_exc_info:
  319.             typ, val, tb = self.usr_exc_info
  320.         else:
  321.             return None
  322.         flist = None
  323.         if flist_oid is not None:
  324.             flist = self.rpchandler.get_remote_proxy(flist_oid)
  325.         while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
  326.             tb = tb.tb_next
  327.         sys.last_type = typ
  328.         sys.last_value = val
  329.         item = StackViewer.StackTreeItem(flist, tb)
  330.         return RemoteObjectBrowser.remote_object_tree_item(item)
  331.